<?php
#-------------------------------------------------------------------------
# Module: Counters - A module to count events
# Version: 1.1
# http://dev.cmsmadesimple.org/projects/??????
# 2012 (c) JoMorg (Fernando Morgado)
#-------------------------------------------------------------------------
# CMS - CMS Made Simple is (c) 2010 by Ted Kulp (wishy@cmsmadesimple.org)
# This project's homepage is: http://www.cmsmadesimple.org
#-------------------------------------------------------------------------
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# Or read it online: http://www.gnu.org/licenses/licenses.html#GPL
#
#-------------------------------------------------------------------------


#-------------------------------------------------------------------------

class Counters extends CMSModule
{
    
  function __construct()
  {
    parent::__construct();
  }

  /**
  * GetName()
  * must return the exact class name of the module.
  * If these do not match, bad things happen.
  *
  * This is the name that's shown in the main Modules
  * page in the Admin.
  *
  * @return string class name
  */

  function GetName()
  {
    return get_class($this); 
  }
  
  /**
  * GetFriendlyName()
  * @return string Friendly name for the module
  */
  function GetFriendlyName()
  {
    return $this->Lang('friendlyname');
  }
 
  /**
  * GetVersion()
  * This can return any string, preferably a number or
  * something that makes sense for designating a version.   
  * @return string version number (can be something like 1.4rc1)
  */
  function GetVersion()
  {
    return '1.1.0.0';
  }

  /**
  * GetHelp()
  * This returns HTML information on the module.
  * @return string Help for this module
  */
  function GetHelp()
  {
    return $this->Lang('help');
  }
  
  /**
  * GetAuthor()
  * This returns a string that is presented in the Module
  * Admin if you click on the "About" link.
  * @return string Author name
  */
  function GetAuthor()
  {
    return 'Fernando Morgado (Jo Morg)';
  }

  /**
  * GetAuthorEmail()
  * This returns a string that is presented in the Module
  * Admin if you click on the "About" link.
  * @return string Authors email
  */
  function GetAuthorEmail()
  {
    return 'jomorg.morg@gmail.com';
  }

  /**
  * GetChangeLog()
  * This returns a string that is presented in the module
  * Admin if you click on the About link. 
  * If your changelog gets really big, you might replace
  * this with an "include" rather than keep it in the Lang
  * file. But then, you'd lose the ability to translate
  * your changelog.
  * @return string ChangeLog for this module
  */
  function GetChangeLog()
  {
    return $this->Lang('changelog');
  }

  /**
  * IsPluginModule()
  * This function returns true or false, depending upon
  * whether users can include the module in a page or
  * template using a smarty tag.
  * 
  * If your module does not get included in pages or
  * templates, return "false" here.
  * @return bool True if this module can be included in page and or template
  */
  function IsPluginModule()
  {
    return true;
  }

  /**
  * HasAdmin()
  * This function returns a boolean value, depending on
  * whether your module adds anything to the Admin area of
  * the site.
  * @return bool True if this module has admin area
  */
  function HasAdmin()
  {
      return true;
  }

  /**
  * GetAdminSection()
  * If your module has an Admin Panel, you can specify
  * which Admin Section (or top-level Admin Menu) it shows
  * up in. This method returns a string to specify that
  * section. Valid return values are:
  * 
  * main        - the Main menu tab.
  * content     - the Content menu
  * layout      - the Layout menu
  * usersgroups - the Users and Groups menu
  * extensions  - the Extensions menu (this is the default)
  * siteadmin   - the Site Admin menu
  * myprefs     - the My Preferences menu
  * ecomm		 - the Ecommerce menu (if ecommerce suite is installed)
  *
  * Note that if you place your module in the main,
  * viewsite, or logout sections, it will show up in the
  * menus, but will not be visible in any top-level
  * section pages.
  * @return string Which admin section this module belongs to
  */
  function GetAdminSection()
  {
    return 'extensions';
  }

  /**
  * GetAdminDescription()
  * If your module does have an Admin Panel, you
  * can have it return a description string that gets shown
  * in the Admin Section page that contains the module.
  * @return string Module description
  */
  function GetAdminDescription()
  {
    return $this->Lang('moddescription');
  }

  /**
  * VisibleToAdminUser()
  * If your module does have an Admin Panel, you
  * can control whether or not it's displayed by the boolean
  * that is returned by this method. This is primarily used
  * to hide modules from admins who lack permission to use
  * them.
  * In this case, the module will only be visible to admins
  * who have "Use Skeleton" permissions.
  * @return bool True if this module is shown to current user
  */
  function VisibleToAdminUser()
  {
    return $this->CheckPermission('Use Counters');
  } 

  /**
  * GetDependencies()
  * This method returns a list of dependencies and
  * minimum version numbers that this module requires.
  *
  * It should return an hash, eg.
  * return array('somemodule'=>'1.0', 'othermodule'=>'1.1');
  * @return hash Hash of other modules this module depends on
  */
  function GetDependencies()
  {
    return array();
  }

  /**
  * MinimumCMSVersion()
  * Your module may require functions or objects from
  * a specific version of CMS Made Simple.
  * 
  * This method returns a string representing the
  * minimum version that this module requires.
  * @return string Minimum cms version this module should work on
  */
  function MinimumCMSVersion()
  {
    return "1.10";
  }

  /**
  * MaximumCMSVersion()
  * You may want to prevent people from using your module in
  * future versions of CMS Made Simple, especially if you
  * think API features you use may change -- after all, you
  * never really know how the CMS MS API could evolve.
  * 
  * This method returns a string representing the
  * maximum version that this module supports.
  */


  function MaximumCMSVersion()
  {
    return "1.12";
  }

  /**
  * SetParameters()
  * This function serves as a module initialization area.
  * Specifically, it enables you to:
  * 1) Simplify your module's tag (if you're writing a plug-in module)
  * 2) Create mappings for your module when using "Pretty Urls".
  * 3) Impose security by controlling incoming parameters
  * 4) Register the events your module handles 
  *
  * 1. Simply module tag:
  * Simple!
  * Calling RegisterModulePlugin allows you to use the tag {...} in your
  * template or page; otherwise, you would have to use the more cumbersome
  * tag {cms_module module='...'}
  *
  * 2. Pretty URLS:
  * Typically, modules create internal links that have
  * big ugly strings along the lines of:
  * index.php?mact=ModName,cntnt01,actionName,0&cntnt01param1=1&cntnt01param2=2&cntnt01returnid=3
  *
  * You might prefer these to look like:
  * /ModuleFunction/2/3
  *
  * To do this, you have to register routes and map
  * your parameters in a way that the API will be able
  * to understand.
  *
  * Also note that any calls to CreateLink will need to
  * be updated to pass the pretty url parameter.
  *
  * 3. Security:
  * By using the RestrictUnknownParams function, your module will not
  * receive any parameters other than the ones you declare here.
  * Furthermore, the parameters your module does receive will be filtered
  * according to the rules you set here.
  *
  * 4. Event Handling
  * If your module generates events, you register that fact in your install method
  * (see method.install.php for an example of this). However, if your module will
  * handle/process/consume events generated by the Core or other modules, you
  * can register that in this method.
  * 
  */ 

  function SetParameters()
  {
    $this->RegisterModulePlugin();

    /*
    * 3. Security
    *
    */
    // Don't allow parameters other than the ones you've explicitly defined
    $this->RestrictUnknownParams();

    // syntax for creating a parameter is parameter name, default value, description

    // counter_id to get counter by id
    $this->CreateParameter('counter_id', -1, $this->Lang('help_counter_id'));
    // counter_id must be an integer
    $this->SetParameterType('counter_id',CLEAN_INT); 


    // name to get counter by name
    $this->CreateParameter('name','',$this->Lang('help_name'));
    // name must be a string
    $this->SetParameterType('name',CLEAN_STRING);     

    // ceiling is the name of Smarty Var to assign ceiling
    $this->CreateParameter('ceiling', -1, $this->Lang('help_ceiling'));
    // ceiling must be an integer
    $this->SetParameterType('ceiling',CLEAN_INT);

    // value is the name of Smarty Var to assign value
    $this->CreateParameter('value', -1, $this->Lang('help_value'));
    // value must be an integer
    $this->SetParameterType('value',CLEAN_INT);

    /*
    * 4. Event Handling
    *

    Typical example: specify the originator, the event name, and whether or not
    the event is removable (used for one-time events)
    */
    $cnts_ecm = cms_utils::get_module('CGEcommerceBase');
    $cnts_Pdts = cms_utils::get_module('Products');

    if (is_object($cnts_ecm) && is_object($cnts_Pdts))
    {
        $this->AddEventHandler( 'CGEcommerceBase', 'OrderCreated', true );   
        $this->AddEventHandler( 'CGEcommerceBase', 'OrderDeleted', true );   
    }             
  }

  /**
  * GetEventDescription()
  * If your module can create events, you will need
  * to provide the API with documentation of what
  * that event does. This method wraps up a simple
  * return of the localized description.
  * @param string Eventname
  * @return string Description for event 
  */
  function GetEventDescription ( $eventname )
  {
    return $this->Lang('event_info_'.$eventname );
  }

  /**
  * GetEventHelp()
  * If your module can create events, you will need
  * to provide the API with documentation of how to
  * use the event. This method wraps up a simple
  * return of the localized description.
  * @param string Eventname
  * @return string Help for event
  */
  function GetEventHelp ( $eventname )
  {
    return $this->Lang('event_help_'.$eventname );
  }

  /**
  * InstallPostMessage()
  * After installation, there may be things you want to
  * communicate to your admin. This function returns a
  * string which will be displayed.
  * 
  * See the note on localization at the top of this file.
  * @return string Message to be shown after installation
  */
  function InstallPostMessage()
  {
    return $this->Lang('postinstall');
  }

  /**
  * UninstallPostMessage()
  * @return string Message to be shown after uninstallation
  */
  function UninstallPostMessage()
  {
    return $this->Lang('postuninstall');
  }

  /**
  * UninstallPreMessage()
  * This allows you to display a message along with a Yes/No dialog box. If the user responds
  * in the affirmative to your message, the uninstall will proceed. If they respond in the
  * negative, the uninstall will be canceled. Thus, your message should be of the form
  * "All module data will be deleted. Are you sure you want to uninstall this module?"
  *
  * If you don't want the dialog, have this method return a FALSE, which will cause the
  * module to uninstall immediately if the user clicks the "uninstall" link.
  * @return string Message to be shown before uninstallation
  */
  function UninstallPreMessage()
  {
    return $this->Lang('really_uninstall');
  }

  /**
  * Your methods here
  * 
  */


  /**
  * DoAction($action, $id, $params, $returnid)
  * This is the main function that gets called if your module
  * is a plug-in type module.
  */
  function DoAction($name,$id,$params,$returnid='')
  {
    # now this is very powerful stuff - except it can be a bit too hazardous for my liking  ->
    $smarty = cmsms()->GetSmarty();

    $smarty->assign_by_ref('cntr_mod',$this);
    $smarty->assign('actionid',$id);
    $smarty->assign('returnid',$returnid);
    # <-
    
    parent::DoAction($name,$id,$params,$returnid);
  }

  function UpdateCounter($id)
  {
    //
  }

                        

  /**
  * Let's handle the event here
  *    
  * @param mixed $originator
  * @param mixed $eventname
  * @param mixed $params
  * @return boolean
  */
  function DoEvent($originator, $eventname, &$params)
  {
    
    # just making sure that Orders is installed
    $cnts_Ordrs = cms_utils::get_module('Orders');
    if (!is_object($cnts_Ordrs )) return; 
    
    /**
    *  CGEcommerceBase  ----    OrderCreated
    */
    
    if ($originator == 'CGEcommerceBase' && $eventname == 'OrderCreated')  
    {
      if (!isset($params['order_id'])) # may seem a stupid check but oddities happen
      {
        $this->Audit(0, $this->Lang('friendlyname'), 'No parameter order_id from CGEcommerceBase event OrderCreated.');   
      }
      else
      {                
        $order = orders_ops::load_by_id($params['order_id']);

        foreach( $order->get_destinations() as $shipment )
        {
          $items = $shipment->get_items();

          foreach( $items as $one_item )
          {
            $tmp_id = $one_item->get_item_id();
            $temp_qnty = $one_item->get_quantity();

            $db = cmsms()->GetDb();
            $query = "SELECT cntr_id, name, ceiling, value, product_id FROM " . cms_db_prefix() . "module_counters WHERE product_id=" . $tmp_id . " ORDER BY cntr_id DESC";
            $dbresult = $db->Execute($query);                    
            
            #$Counters = array();
            while ($dbresult && $row = $dbresult->FetchRow())
            {
              $cntr = new stdClass();
              $cntr->id = $row['cntr_id'];         
              $cntr->name = $row['name'];     
              $cntr->value = $row['value'] + $temp_qnty;     
              $cntr->ceiling = $row['ceiling'];     
              $cntr->product_id = $row['product_id'];     
              #$Counters[] = $cntr;
                
            } 
              
              #update Counter
              $query =    'UPDATE '.cms_db_prefix() .
                          'module_counters set value=? where cntr_id = ?';
                          $result = $db->Execute($query, array($cntr->value, $cntr->id));
                          $params['module_message'] = $this->Lang('updated_record');
                      
              if ( $cntr->value >= $cntr->ceiling )
              {   
                  $this->SendEvent('OnCounterCeilingReached', array(  'CounterName' => $cntr->name, 
                                                                      'CounterID' => $cntr->id,
                                                                      'CounterValue' => $cntr->value,
                                                                      'CounterCeiling' => $cntr->id
                                                                  ));
              }                                               

          } #  foreach items
           
        }# foreach order     
             
      }# isset
      
    }# if originator 
    
    
    /**
    *  CGEcommerceBase  ----    OrderDeleted
    */
    
    if ($originator == 'CGEcommerceBase' && $eventname == 'OrderDeleted')  
    {
        if (!isset($params['order_id'])) # may seem a stupid check but oddities happen
        {
            $this->Audit(0, $this->Lang('friendlyname'), 'No parameter order_id from CGEcommerceBase event OrderCreated.');   
        }
        else
        {

            
            $order = orders_ops::load_by_id($params['order_id']);
            
            foreach( $order->get_destinations() as $shipment )
            {
              $items = $shipment->get_items();

              foreach( $items as $one_item )
              {
                $tmp_id = $one_item->get_item_id();
                $temp_qnty = $one_item->get_quantity();

                $db = cmsms()->GetDb();
                $query = "SELECT cntr_id, name, ceiling, value, product_id FROM " . cms_db_prefix() . "module_counters WHERE product_id=" . $tmp_id . " ORDER BY cntr_id DESC";
                $dbresult = $db->Execute($query);
                   
                  
                $Counters = array();
                while ($dbresult && $row = $dbresult->FetchRow())
                {
                  $cntr = new stdClass();
                  $cntr->id = $row['cntr_id'];         
                  $cntr->name = $row['name'];     
                  $cntr->value = $row['value'] - $temp_qnty;     
                  $cntr->ceiling = $row['ceiling'];     
                  $cntr->product_id = $row['product_id'];     
                  $Counters[] = $cntr;
                } 
                  
                #update Counter
                $query =    'UPDATE '.cms_db_prefix() .
                            'module_counters set value=? where cntr_id = ?';
                $result = $db->Execute($query, array($cntr->value, $cntr->id));
                $params['module_message'] = $this->Lang('updated_record');

              } #  foreach items
               
          } # foreach order  
                                     
        }# isset
        
    }# if originator 
       
  }

} //end class
?>
